////////////////////////////////////////////////////////////////////////////////
// Filename: window.cpp
////////////////////////////////////////////////////////////////////////////////
#include "window.hpp"
#include "resource.hpp"
#include "iostream"

Window::Window(LPCSTR applicationName) {
	m_width = GetSystemMetrics(SM_CXSCREEN);
	m_height = GetSystemMetrics(SM_CYSCREEN);
	m_posX = 0;
	m_posY = 0;
	m_applicationName = applicationName;
	m_hInstance = NULL;
	m_hWnd = NULL;
}

Window::~Window() {

}

bool Window::Initialize() {
	WNDCLASSEX wc;
	LPCSTR szClassName = "win32app";

	s_applicationHandle = this;
	m_hInstance = GetModuleHandle(NULL);

	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = m_hInstance;
	wc.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_MARK_IV));
	wc.hIconSm = wc.hIcon;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = szClassName;
	wc.cbSize = sizeof(WNDCLASSEX);

	RegisterClassEx(&wc);

	m_posX = (GetSystemMetrics(SM_CXSCREEN) - GetWidth()) / 2;
	m_posY = (GetSystemMetrics(SM_CYSCREEN) - GetHeight()) / 2;

	m_hWnd = CreateWindowEx(WS_EX_APPWINDOW, szClassName, m_applicationName,
			WS_CAPTION | WS_SYSMENU, m_posX, m_posY, GetWidth(), GetHeight(), NULL,
			NULL, m_hInstance, NULL);
	if (!m_hWnd) {
		return false;
	}

	ShowWindow(m_hWnd, SW_SHOW);
	SetForegroundWindow(m_hWnd);
	SetFocus(m_hWnd);

	m_input = new MarkIV::System::Input();
	if (!m_input) {
		return false;
	}

	m_input->Initialize();

	return true;
}

void Window::Shutdown() {
	if (m_input) {
		delete m_input;
		m_input = 0;
	}

	DestroyWindow(m_hWnd);
	m_hWnd = NULL;

	UnregisterClass(m_applicationName, m_hInstance);
	m_hInstance = NULL;

	s_applicationHandle = NULL;
}

int Window::GetWidth() {
	return m_width;
}

int Window::GetHeight() {
	return m_height;
}

LPCSTR Window::GetName() {
	return m_applicationName;
}

HWND Window::GetHandle() {
	return m_hWnd;
}

MarkIV::System::Input* Window::GetInput() {
	return m_input;
}

void Window::SetWidth(int width) {
	m_width = width;

	m_posX = (GetSystemMetrics(SM_CXSCREEN) - m_width)  / 2;
	SetWindowPos(m_hWnd, NULL, m_posX, m_posY, m_width, m_height, 0);
}

void Window::SetHeight(int height) {
	m_height = height;

	m_posY = (GetSystemMetrics(SM_CYSCREEN) - m_height) / 2;
	SetWindowPos(m_hWnd, NULL, m_posX, m_posY, m_width, m_height, 0);
}

void Window::SetResolution(int width, int height) {
	SetWidth(width);
	SetHeight(height);
}

LRESULT CALLBACK Window::MessageHandler(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
	switch (uMessage) {
	case WM_KEYDOWN: {
		m_input->KeyDown((unsigned int)wParam);
		return 0;
	}
	case WM_KEYUP: {
		m_input->KeyUp((unsigned int)wParam);
		return 0;
	}
	default:
		return DefWindowProc(hWnd, uMessage, wParam, lParam);
	}
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
	switch (uMessage) {
	case WM_DESTROY:
	case WM_CLOSE:
		PostQuitMessage(0);
		return 0;
	default:
		return s_applicationHandle->MessageHandler(hWnd, uMessage, wParam, lParam);
	}
}
